import datetime
import random
from models.model import *
    
# Max title length of competitions
maxTitleLength=50
# Max stockname length
maxStockLength=50
# Max words per arena entity
maxWordsPerArenaEntity=3
# Max Amount chars length in pages where invetment value is required
maxAmountLength=20
# How many member to display in each arena entity before display (and x others)...
ArenaDisplayNumMembers=3
# Inital sum
InitSum=100.0
# Index template path
controllersIndexPath='../views/index.html'
    
def getSID():
        """ Return SID for google access """
        res=random.randint(0, 3)
        if res==0:
            return "SID=DQAAAG0AAACWyUGMNq4E8TstbWj1BvOFyTh9Cqj41_IR_wir9vT2zEzc9YxkA4K4Z5T_jRNo65rhkWZfdbZpqMwugfI34RGn6DTP-Mj65uLgsrmlX9-mENaw63zYYdBo42JScsGWMSigoov59iXMN44laXm368b3"
        elif res==1:
            return "SID=DQAAAG0AAAAOJOIEZULfWymE1LRib6Th8Fql7G0kwuSwpMbClHaYIA8nDzBo9LAcpvHLRHrIckHvNGw2xXLTNwxTlGzaLZl7bpXKvqscjQKXYHI9c2ZgNTciszU_Gr9o4y23Xnw2mV5r1QjyNKHYLQ9o7pg4uSvk"
        elif res==2:
            return "SID=DQAAAGwAAACIv6WCe13XMEdA4lbbzLCLGI-5RlMCv5AqC11-hLbAftp3fSDvaRmiwX-U2BRQccDyweMCxQs4eX27ZopLwxJFDD4aF_5XfrgB_BOgouts8Ball9W3k4cOtT3m44C8PwdAxXkZ18jgHfOiw4XKVeNa"
        elif res==3:
            return "SID=DQAAAG0AAADZZ9Lbb2zT21qPeq0BgaMxGd_6K8u-SEAK6ID3Sipmrn3abSx4uEKRw5egD9xQFAKa1r1qhXB0A3Tt7mluhVYHlukFcN5DiXd3Xm3QWcIdn7h_YGkbypYPw-wPdth2uz2JL0R0GoABMWEnFk-syO3S"

def getMonkeyName(monkeyNum):
    """ Get monkey name by ID """
    if monkeyNum==1: 
        return "trendse.speculative@gmail.com"
    elif monkeyNum==2: 
        return "trendse.smart@gmail.com"
    elif monkeyNum==3: 
        return "trendse.random@gmail.com"
    else:
        return


def getCurrentUserGraph(user):    
    """ Load user history from database """
    q_1 = db.GqlQuery("SELECT * FROM HistoryUsers " +
    "WHERE tuser = :1 LIMIT 0,1", user)
    # If user is using app for first time (=his info in not in TrendUsers table)
    # then initialize his info
    if q_1.count()==0:
        # THE INIT BANK ACCOUNT SUM
        historyuser = HistoryUsers()
        historyuser.tuser = user
        historyuser.history= [InitSum]
        historyuser.put()
        return historyuser
    else:
        q_1=q_1.fetch(1)
        return q_1[0]

def getCurrentUser(user):
    """ Load user info from database """
    q_1 = db.GqlQuery("SELECT * FROM TrendUsers " +
    "WHERE tuser = :1 LIMIT 0,1", user)
    # If user is visiting for the first time
    if q_1.count()==0:

        # THE INIT BANK ACCOUNT SUM
        initsum=InitSum   
        trenduser = TrendUsers()
        trenduser.tuser = user
        trenduser.bankamount=initsum
        trenduser.lastweekamount=initsum
        trenduser.totalamount=initsum
        trenduser.put()
        getCurrentUserGraph(user)
        
        # currect_user is the new user
        return trenduser
    
    else:
        # currect_user is the user loaded from the database
        q_1=q_1.fetch(1)
        return q_1[0]
            
def fetchUser(user):
    """ Fetch user from datastore (use in legendary) """
    q_1 = db.GqlQuery("SELECT * FROM TrendUsers WHERE tuser = :1 LIMIT 0,1", user)
    return q_1[0]

    
# buy - flag = o ; sell - flag = 1
def moveToNewsFeed(stock,sref,flag):
    """ Move stock action or ETF to news feed (buy (flag=0) or sell (flag=1)) """
    action = NewsFeeds()
    action.buyValue = stock.buyValue
    action.buydate = stock.buydate
    action.buyer = stock.buyer
    action.currValue = stock.currValue
    if stock.stockref!=None:
        action.stockname = stock.stockref.stockname
        action.stockref=sref
    else:
        action.stockname = stock.basketref.categoryref.category
        action.etfref=sref
        action.stockETF = 1 # ETF = 1
    action.actiondate = datetime.datetime.now()
    action.flag = flag
    action.put()
    

def resetUser(user):
    """ Reset user portfolio function (legendary) """
    q_1 = db.GqlQuery("SELECT * FROM Stocks " +
    "WHERE buyer = :1", user)
    for entity in q_1:
        entity.delete()
        
    # Delete user history
    q_1 = db.GqlQuery("SELECT * FROM HistoryUsers " +
    "WHERE tuser = :1", user)
    for entity in q_1:
        entity.delete()
        
    # Init bank amount        
    q_2 = db.GqlQuery("SELECT * FROM TrendUsers " +
    "WHERE tuser = :1 LIMIT 0,1", user)
    trenduser=q_2[0]
    trenduser.totalamount=float(100)
    trenduser.bankamount=float(100)
    trenduser.put()
    

def getPerInfo(percentCng):
    """ Set percentage display and color (red, green, +, -) and use correct format to print the percentage """
    if percentCng==1:
        printPercentage=0.0
        fontColor="#000000"
        changeSign="%"
    elif percentCng<1:
        printPercentage=100*(1-percentCng)
        fontColor="#9C0416"
        #Old design: changeSign="-%"
        changeSign="<img src=\"images/rarrow.gif\" width=\"6\" height=\"6\">%"
    else:
        printPercentage=(100*percentCng)-100
        fontColor="#14BE44"
        changeSign="<img src=\"images/garrow.gif\" width=\"6\" height=\"6\">%"
    return printPercentage, fontColor, changeSign


def lastWeekAmount():
    """ Save users week amount for top earners calculations """
    q_1 = db.GqlQuery("SELECT * FROM TrendUsers")
    for trenduser in q_1:
        # Update percentage of change for this week
        trenduser.lastweekprcnt=round(trenduser.totalamount/trenduser.lastweekamount,2)
        # Update the new last week amount to be the current amount
        trenduser.lastweekamount=trenduser.totalamount
        # Update database
        trenduser.put()
        

def getStockHolders(stockname):
    """ Get the number of holders for a given stock"""
    q_1 = db.GqlQuery("SELECT * FROM StocksData WHERE stockname=:1 LIMIT 0,1" , stockname)
    q_1=q_1.fetch(1)
    if len(q_1)==0:
        return 0
    else:
        return q_1[0].stockcounter

def getPopular(stockholders):
    """ Return  popularity text for stock holders number (API use) """
    q_1 = db.GqlQuery("SELECT * FROM Stocks")
    # Calculate % popularity
    popularityNum=int(float(stockholders)/float(q_1.count())*100)
    #print (stockholders*q_1.count())/100
    if popularityNum>80:
        return popularityNum, "Extreme"
    elif popularityNum>50:
        return popularityNum, "Popular"
    elif popularityNum>20:
        return popularityNum, "Normal"
    else:
        return popularityNum, "Weak"


def getErrorMsg(errorNum):
    """ List of error msgs """
    if errorNum==0:
        return "You don't have enough money at your bank to buy at this value"
    elif errorNum==1:
        return "Please insert valid stock name (English and numbers only)"
    elif errorNum==2:
        return "Entered stock value is not valid"
    elif errorNum==3:
        return "Can not sell this stock (is it really yours?!)"
    elif errorNum==4:
        return "ETF name is not valid"
    elif errorNum==5:
        return "Invalid competition's start date, end date or amount entered"
    elif errorNum==6:
        return "When opening a competition it is required to choose your own bet"
    elif errorNum==7:
        return "When opening a competition it is required to choose your own bet AND also insert at least 2 options"
    elif errorNum==8:
        return "You do not have enough money at your bank account to open this competition"
    elif errorNum==9:
        return "Joining a competition is enabled only when you have enough money at your bank account. Also joining is possible only before the competition begins and you chose a valid bet"
    elif errorNum==9:
        return "Joining a competition is enabled only before it begins, you have enough money at your bank account and you chose a valid bet"
    elif errorNum==10:
        return "You do not have enough money at your advertiser account to open this competition"
    elif errorNum==11:
        return "Each stock name must not exceed %d characters and contain English letter and numbers only" % maxStockLength
    elif errorNum==12:
        return "Competition title can not be null or exceed %d chars" % maxTitleLength
    elif errorNum==13:
        return "Please insert a valid advertisment amount"
    elif errorNum==14:
        return "Please insert a valid number for alerts"
    elif errorNum==15:
        return "There has been a problem with one of the external sources TrendSE fetches data from. Please try again."
    else:
        return -1
        
def buildErrorList(msg):
    """ Build lists of multiple error msgs """
    errorList=[]
    msgList = msg.split('A')
    msgList=set(msgList)
    # Maximum of 10 error msgs per page
    if len(msgList)<=10:
        for currMsg in msgList:
            # Check for valid float stock value
            try:
                msgvalue=int(currMsg)
                res=getErrorMsg(msgvalue)
                if res!=-1:
                    errorList.append(res)
            # Invalid error msg
            except:
                continue
    return errorList


def computeTimeElapse(compStartDay):
    """ computing the delta tie from today """
    today=datetime.datetime.today()
    #competition starts at 24:00
    time=datetime.time(0)
    #CompStratDate is a combination of compStartday and time
    compStratDate=datetime.datetime.combine(compStartDay, time)
    deltaTime=compStratDate-today
    hours=deltaTime.seconds/3600
    hourToStart=deltaTime.days*24+hours
    minToStart=(deltaTime.seconds%3600)/60
    secToStart=(deltaTime.seconds%3600)%60
    
    return hourToStart, minToStart, secToStart
   
def human_timedelta(ts):
    """Converts a timedelta into a human readable description of time elapsed.
  If the input is a datetime, it is subtracted from the current datetime.
  """
    if isinstance(ts, datetime.datetime):
        delta = datetime.datetime.now() - ts
    else:
        delta = ts
    elapsed = float(timedelta_to_seconds(delta))
    if elapsed <= 90:
        return "%d seconds" % (elapsed,)
    elapsed /= 60
    if elapsed <= 90:
        return "%d minutes" % (elapsed,)
    elapsed /= 60
    if elapsed <= 48:
        return "%d hours" % (elapsed,)
    elapsed /= 24
    return "%d days" % (elapsed,)

def timedelta_to_seconds(delta):
    """Converts a datetime.timedelta into a number of seconds."""
    return delta.days * 86400.0 + delta.seconds


def publishNewsFeeds (user,user2):
    """ Prepare news feed text for account page """
    if (user2==0):
        q_1 = db.GqlQuery("SELECT * FROM NewsFeeds ORDER BY actiondate DESC,stockname")
    else:
        q_1 = db.GqlQuery("SELECT * FROM NewsFeeds WHERE buyer=:1 ORDER BY actiondate DESC,stockname LIMIT 0,5",user2)

    newsfeeds=""    
    counter=0
    for p in q_1:
        if (p.buyer==user and user2==0):
            continue
        else:
            counter+=1
        change = "profit"
        linkText="<a href=\"/buy?q=%s\">%s</a>" % (p.stockname,p.stockname)
        # Check if stock is still in stocksData
        try:
            if p.stockETF==1:
                percentChange = p.etfref.precentChange
                linkText="<a href=\"/trendProfile?TKey=%s\">%s</a>" % (p.etfref.key(),p.stockname)
                
            else:
                percentChange = p.stockref.precentChange
                linkText="<a href=\"/trendProfile?TKey=%s\">%s</a>" % (p.stockref.key(),p.stockname)
        except:
            percentChange = 1.0
            
            
        printPercentage, fontColor, changeSign= getPerInfo(percentChange)
    
        # Compute when the transaction made (days, hours, minutes)
        delta = datetime.datetime.now()-p.actiondate 
        
        newsfeeds+="<div class=\"feedWrap\">"
        newsfeeds+="<div class=\"feed-news\"><a href=\"/userProfile?q=%s\">%s</a>" % (p.buyer.email(),p.buyer)
        
        # buy
        if (p.flag==0): 
            if p.stockETF==0:
                stockTypeText="trend"
            else:
                stockTypeText="ETF"
            newsfeeds+=" bought the %s %s for $%.2f" % (stockTypeText, linkText,p.buyValue)
            imgActionType="buy.gif"
        
        # sell
        if (p.flag==1): 
            earn = p.currValue-p.buyValue
            if (earn<0):
                change = "loss"
                fontColorEarn = "#9C0416"
            else:
                fontColorEarn = "#14BE44"    
            if p.stockETF==0:
                newsfeeds+=" sold the Trend <a href=/buy?q=%s>%s</a> he bought in <font color=%s>%d$</font> %s" % (p.stockname,p.stockname,fontColorEarn,earn,change)
            else:
                newsfeeds+=" sold the ETF <a href=/buy?q=%s>%s</a> he bought in <font color=%s>%d$</font> %s" % (p.stockname,p.stockname,fontColorEarn,earn,change)
            imgActionType="sell.gif"
        
        newsfeeds+="<BR /><span class=\"feed-time\"><img src=\"/images/%s\"> %s ago</span></div>" % (imgActionType, human_timedelta(delta))
        newsfeeds+="<div class=\"feed-stock\">%s<BR /><span class=\"per-print\" style=\"color:%s;\">%s%.2f</span></div></div>" % (p.stockname,fontColor,changeSign,printPercentage)
        newsfeeds+="<div style=\"clear:both;\"><img src=\"images/break-line.gif\"></div>"
        
        if counter==5:
            break;  
        
    if counter==0:
        newsfeeds+="<div>No newsfeeds available yet</div>"
            
    return newsfeeds
        
def createToolTip(message):
    """ Tooltip texts to display by msg number """
    text=""
    if (message=="category"):
        text = "View best performing stocks by categories"
    elif (message=="alert"):
        text = "Here you can request to be informed by <BR/> Email about changes in your portfolio"
    elif (message=="portfolio"):
        text = "All your trends in one place"
    elif (message=="statistics"):
        text = "Explore the outstanding trends <BR/> Performances on TrendSE"
    elif (message=="portfolio competition"):
        text="Compete with your friends - who <BR/> has the most profitable portfolio"
    elif (message=="arena competition"):
        text="Join an arena, bet on who will be the stock that rises the most<BR />and win the whole pot"
    elif (message=="advertise"):
        text="Advertiser? Here you can open and <BR />manage your arenas and reveal what <BR />people think about <strong>your trends!</strong>  "
    elif (message=="buy"):
        text="Buy the words you think will be the next <strong> Trend</strong>"	

    toolTip = "<a href=\"#\" class=\"toolclass\" title=\"%s\"><img src=\"/images/helptool.gif\" border=\"0\"></a>" % text

    return toolTip
        
